package com.gzhryc.system;

import com.gzhryc.common.IDTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.config.DefaultEnum;
import com.gzhryc.common.config.PropertyTools;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.common.secruity.EncryptTools;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.system.dao.ManagerDao;
import com.gzhryc.system.dao.ManagerRoleDao;
import com.gzhryc.system.dao.db.Manager;
import com.gzhryc.system.dao.db.ManagerRole;
import com.gzhryc.system.dao.db.Role;
import com.gzhryc.system.dao.enums.ManagerEnum;
import com.gzhryc.system.dao.models.ManagerRoleInfo;
import com.gzhryc.system.dto.ManagerSearch;
import org.apache.commons.lang3.StringUtils;

import java.sql.SQLException;
import java.util.*;

/**
 * 后台用户管理
 * 
 * @author 张浩
 * @version 0.1.0
 */
public class ManagerService {

	static Logger log = Logger.getLogger(ManagerService.class);
	
	public static ManagerService self() {
		return MultiDBTools.getService(ManagerService.class, true);
	}

	public static ManagerService self(String jdbcKey) {
		return MultiDBTools.getService(jdbcKey,ManagerService.class, true);
	}

	ManagerDao managerDao;
	ManagerRoleDao managerRoleDao;
	
	public ManagerService(String jdbcKey) {
		managerDao = new ManagerDao(jdbcKey);
		managerRoleDao = new ManagerRoleDao(jdbcKey);
	}

	/**
	 * 获取管理员用户
	 * 
	 * @return
	 * @throws LogicException 
	 */
	public synchronized Manager initialSuperAdminUser(String roleCode) throws LogicException {
		Conditions condition = new Conditions(Manager.class);
		condition.and().is("type", ManagerEnum.Type.SuperAdmin.index());
		try {

			Manager manager = managerDao.get(condition);
			if (manager == null) {
				String loginName = PropertyTools.get().getString(SysConstants.CFG_DEF_LOGIN_NAME);
				String loginPwd = PropertyTools.get().getString(SysConstants.CFG_DEF_LOGIN_PWD);
				if(StringTools.isNotBlank(loginName) && StringTools.isNotBlank(loginPwd)) {
					manager = new Manager();
					manager.setName(ManagerEnum.Type.SuperAdmin.note());
					manager.setLoginName(loginName);
					manager.setLoginPwd(loginPwd);
					manager.setType(ManagerEnum.Type.SuperAdmin.index());
					manager.setStatus(DefaultEnum.Status.Usable.index());
					manager.setCreateDate(new Date());
					if(!add(manager, false)) {
						manager = null;
					}
				}else {
					throw new LogicException("未配置默认登陆账号");
				}
			}
			if(manager != null) {
				Role role = RoleService.self(managerDao.getJdbcKey()).getByCode(roleCode);
				if (role != null) {
					addManagerRole(manager.getId(), role.getId());
				}
			}
			return manager;
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 分页查询数据
	 * 
	 * @param search
	 * @param pageNo
	 * @param pageLimit
	 * @return
	 */
	public List<Manager> findBySearch(ManagerSearch search, Integer pageNo, Integer pageLimit) {
		Conditions condition = new Conditions(Manager.class);
		if (search != null) {
			condition.and().likeBoth("name", search.getName());
			condition.and().likeBoth("loginName", search.getLoginName());
			condition.and().is("type", search.getType());
			condition.and().is("status", search.getStatus());
		}
		try {
			return managerDao.findByCondition(condition, pageNo, pageLimit);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取拥有某个权限的管理员
	 * 
	 * @param roleId
	 * @param pageNo
	 * @param pageLimit
	 * @return
	 */
	public List<Manager> findByRoleId(Long roleId, Integer pageNo, Integer pageLimit) {
		try {
			return managerDao.findByRoleId(roleId, pageNo, pageLimit);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 统计查询数量
	 * 
	 * @param search
	 * @return
	 */
	public Long countBySearch(ManagerSearch search) {
		Conditions condition = new Conditions(Manager.class);
		if (search != null) {
			condition.and().likeBoth("name", search.getName());
			condition.and().likeBoth("loginName", search.getLoginName());
			condition.and().is("type", search.getType());
			condition.and().is("status", search.getStatus());
		}
		try {
			return managerDao.count(condition);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return 0L;
	}

	public List<ManagerRoleInfo> findRoleInfoByManagerIds(List<Long> managerIds) {
		Conditions conditions = new Conditions(ManagerRole.class);
		conditions.and().in("managerId",managerIds);
		try {
			List<ManagerRole> managerRoleList = managerRoleDao.findByCondition(conditions);
			if(managerRoleList != null && managerRoleList.size() > 0){
				Map<Long, ManagerRoleInfo> map = new HashMap<>();
				List<Long> roleIds = new ArrayList<>();
				for(ManagerRole managerRole : managerRoleList){
					if(!roleIds.contains(managerRole.getRoleId())){
						roleIds.add(managerRole.getRoleId());
					}
				}

				List<Role> roleList = RoleService.self().findByIds(roleIds);

				for(ManagerRole managerRole : managerRoleList){
					ManagerRoleInfo item = map.get(managerRole.getManagerId());
					if(item == null){
						item = new ManagerRoleInfo();
						item.setManagerId(managerRole.getManagerId());
						map.put(item.getManagerId(),item);
					}
					if(roleList != null && roleList.size() > 0){
						for(Role role : roleList){
							if(role.getId().equals(managerRole.getRoleId())){
								if(item.getRoleIds() == null){
									item.setRoleIds(role.getId().toString());
								}else{
									item.setRoleIds(item.getRoleIds()+ "," +role.getId());
								}

								if(item.getRoleNames() == null){
									item.setRoleNames(role.getName());
								}else{
									item.setRoleNames(item.getRoleNames()+ "," +role.getName());
								}
								break;
							}
						}
					}
				}
				return new ArrayList<>(map.values());
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 根据登录账号查询用户信息
	 * 
	 * @param loginName
	 * @return
	 */
	public Manager getByLoginName(String loginName) {
		if (StringUtils.isNotBlank(loginName)) {
			Conditions condition = new Conditions(Manager.class);
			condition.and().is("loginName", loginName);
			try {
				return managerDao.get(condition);
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
		return null;
	}

	/**
	 * 登录功能
	 * 
	 * @param loginName
	 * @param loginPwd
	 * @return
	 * @throws LogicException
	 */
	public Manager login(String loginName, String loginPwd) throws LogicException {
		Manager manager = getByLoginName(loginName);
		if (manager != null) {
			if (manager.getStatus().equals(DefaultEnum.Status.Unusable.index())) {
				throw new LogicException("账号未开通，请联系管理员");
			}
			if (manager.getLoginPwd().equals(EncryptTools.md5(loginPwd))) {
				String token = IDTools.getUUID();
				int count = 0;
				while(count < 3 && this.getByToken(token) != null) {
					token = IDTools.getUUID();
					count++;
				}
				if(count < 3) {
					Manager updateEntity = new Manager();
					updateEntity.setId(manager.getId());
					updateEntity.setLastLoginDate(new Date());
					updateEntity.setToken(token);
					
					try {
						if(managerDao.updateNotNull(updateEntity) > 0) {
							manager.setToken(token);
							manager.setLastLoginDate(updateEntity.getLastLoginDate());
							return manager;
						}
					} catch (SQLException e) {
						log.error(e.getMessage(),e);
					}
				}
			}
		}
		return null;
	}

	public String login(Long id){
		if(id != null) {
			Manager updateEntity = new Manager();
			updateEntity.setId(id);
			updateEntity.setLastLoginDate(new Date());
			String token = IDTools.getUUID();
			int count = 0;
			while(count < 3 && this.getByToken(token) != null) {
				token = IDTools.getUUID();
				count++;
			}
			if(count < 3) {
				updateEntity.setToken(token);
				try {
					if (managerDao.updateNotNull(updateEntity) > 0) {
						return token;
					}
				} catch (SQLException e) {
					log.error(e.getMessage(), e);
				}
			}
		}
		return null;
	}

	public Manager getById(Long id) {
		if(id != null) {
			try {
				return managerDao.getById(id);
			} catch (SQLException e) {
				log.error(e.getMessage(),e);
			}
		}
		return null;
	}
	
	public Manager getByToken(String token) {
		if(StringTools.isNotBlank(token)) {
			Conditions condition = new Conditions(Manager.class);
			condition.and().is("token", token);
			try {
				return managerDao.get(condition);
			} catch (SQLException e) {
				log.error(e.getMessage(),e);
			}
		}
		return null;
	}
	
	public void logout(Long id) {
		if(id != null) {
			Map<String,Object> data = new HashMap<String,Object>();
			data.put("id", id);
			data.put("token", null);
			
			try {
				managerDao.update(data);
			} catch (SQLException e) {
				log.error(e.getMessage(), e);
			}
		}
	}

	/**
	 * 注册用户
	 * 
	 * @param manager
	 * @return
	 * @throws LogicException
	 */
	public synchronized boolean register(Manager manager, List<Long> roles) throws LogicException {
		// 检查登录名是否冲突
		Manager entity = getByLoginName(manager.getLoginName());
		if (entity != null) {
			throw new LogicException("登录名已存在");
		}
		manager.setLoginName(manager.getLoginName().trim());
		manager.setLoginPwd(EncryptTools.md5(manager.getLoginPwd()));
		manager.setToken(IDTools.getUUID());
		manager.setType(ManagerEnum.Type.Admin.index());
		manager.setStatus(DefaultEnum.Status.Usable.index());
		if(StringUtils.isBlank(manager.getToken())){
			manager.setToken(IDTools.getUUID());
		}
		manager.setCreateDate(new Date());
		JdbcSession.begin();
		try {
			if (managerDao.insert(manager) > 0) {
				// 添加角色
				if (roles != null) {
					for (Long roleId : roles) {
						ManagerRole item = new ManagerRole();
						item.setManagerId(manager.getId());
						item.setRoleId(roleId);
						item.setCreateDate(new Date());
						managerRoleDao.insert(item);
					}
				}
				JdbcSession.commit();
				return true;
			}
		} catch (SQLException e) {
			log.error(e.getMessage(),e);
			JdbcSession.rollback();
		} finally {
			JdbcSession.end();
		}

		return false;
	}

	/**
	 * Title: addRoleRelation Description: 添加管理员和角色关系
	 * 
	 * @param manager
	 * @param roles
	 * @return
	 * @throws LogicException
	 */
	public synchronized boolean addRoleRelation(Manager manager, List<Long> roles) {
		try {
			// 添加关系
			if (roles != null) {
				for (Long roleId : roles) {
					ManagerRole item = new ManagerRole();
					item.setManagerId(manager.getId());
					item.setRoleId(roleId);
					item.setCreateDate(new Date());
					managerRoleDao.insert(item);
				}
			}
			return true;
		} catch (SQLException e) {
			e.printStackTrace();
		}

		return false;
	}

	public synchronized boolean add(Manager manager, boolean md5) throws LogicException {
		// 检查登录名是否冲突
		Manager entity = getByLoginName(manager.getLoginName());
		if (entity != null) {
			throw new LogicException("登录名已存在");
		}
		if (md5) {
			manager.setLoginPwd(EncryptTools.md5(manager.getLoginPwd()));
		} else {
			manager.setLoginPwd(manager.getLoginPwd());
		}
		if (manager.getType() == null) {
			manager.setType(ManagerEnum.Type.Admin.index());
		}
		if (manager.getStatus() == null) {
			manager.setStatus(DefaultEnum.Status.Usable.index());
		}
		if(StringUtils.isBlank(manager.getToken())){
			manager.setToken(IDTools.getUUID());
		}
		manager.setCreateDate(new Date());
		try {
			if (managerDao.insert(manager) > 0) {
				return true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 根据用户ID修改用户信息
	 * 
	 * @param manager
	 * @return
	 * @throws LogicException
	 */
	public boolean updateInfo(Manager manager, List<Long> roles) throws LogicException {
		JdbcSession.begin();
		try {
			if (managerDao.updateNotNull(manager) > 0) {
				// 删除角色信息，重新录入
				managerRoleDao.deleteByManagerId(manager.getId());
				if (roles != null) {
					for (Long roleId : roles) {
						ManagerRole item = new ManagerRole();
						item.setManagerId(manager.getId());
						item.setRoleId(roleId);
						managerRoleDao.insert(item);
					}
				}
				JdbcSession.commit();
				return true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
			JdbcSession.rollback();
		} finally {
			JdbcSession.end();
		}
		return false;
	}

	public boolean updateInfo(Manager manager) throws LogicException {
		try {
			// 检查登录名是否冲突
			Manager entity = getByLoginName(manager.getLoginName());
			if (entity != null && !entity.getId().equals(manager.getId())) {
				throw new LogicException("登录名已存在");
			}
			if (managerDao.updateNotNull(manager) > 0) {
				return true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 切换用户状态
	 * 
	 * @param id
	 * @return
	 */
	public boolean changeStatus(Long id) {
		try {
			Manager manager = managerDao.getById(id);
			if (manager != null) {
				if (manager.getStatus().equals(DefaultEnum.Status.Unusable.index())) {
					manager.setStatus(DefaultEnum.Status.Usable.index());
				} else {
					manager.setStatus(DefaultEnum.Status.Unusable.index());
				}
				if (managerDao.updateNotNull(manager) > 0) {
					return true;
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 根据ID删除用户
	 * 
	 * @param id
	 * @return
	 * @throws LogicException
	 */
	public boolean deleteById(Long id) throws LogicException {
		try {
			Manager manager = managerDao.getById(id);
			if (manager != null) {
				if (manager.getType().equals(ManagerEnum.Type.SuperAdmin.index())) {
					throw new LogicException("管理员用户不容许删除");
				}
				if (managerDao.deleteById(id) > 0) {
					return true;
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * Title: deleteByManager Description: 根据管理员id删除与角色的关系
	 * 
	 * @param id
	 * @return
	 * @throws LogicException
	 */
	public boolean deleteRoleByManager(Long id) {
		try {
			Manager manager = managerDao.getById(id);
			if (manager != null) {
				Conditions condition = new Conditions(ManagerRole.class);
				condition.and().is("managerId", manager.getId());
				boolean b = managerRoleDao.deleteByCondition(condition) > 0;
				return b;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}
	
	/**
	 * 移除管理员的指定角色
	 * @param managerId
	 * @param roleId
	 * @return
	 */
	public boolean removeRoleFormManager(Long managerId,Long roleId) {
		if(managerId != null && roleId != null) {
			ManagerRole mngRole = getManagerRole(managerId, roleId);
			if(mngRole != null) {
				try {
					return managerRoleDao.deleteById(mngRole.getId()) > 0;
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}

	/**
	 * 重置密码
	 * 
	 * @param id
	 * @param loginPwd
	 * @return
	 */
	public boolean resetPwd(Long id, String loginPwd) {
		Manager manager = new Manager();
		manager.setId(id);
		manager.setLoginPwd(EncryptTools.md5(loginPwd));
		manager.setPwdUpdateDate(new Date());
		try {
			if (managerDao.updateNotNull(manager) > 0) {
				return true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	/**
	 * 检验密码
	 * 
	 * @param id
	 * @param loginPwd
	 * @return
	 */
	public boolean checkPwd(Long id, String loginPwd) {
		try {
			Manager manager = managerDao.getById(id);
			if (manager != null) {
				if (manager.getLoginPwd().equals(EncryptTools.md5(loginPwd))) {
					return true;
				}
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return false;
	}

	public ManagerRole getManagerRole(Long managerId, Long roleId) {
		Conditions condition = new Conditions(ManagerRole.class);
		condition.and().is("managerId", managerId);
		condition.and().is("roleId", roleId);
		try {
			return managerRoleDao.get(condition);
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return null;
	}

	public synchronized boolean addManagerRole(Long managerId, Long roleId) {
		if (managerId != null && roleId != null) {
			ManagerRole managerRole = getManagerRole(managerId, roleId);
			if (managerRole == null) {
				managerRole = new ManagerRole();
				managerRole.setManagerId(managerId);
				managerRole.setRoleId(roleId);
				managerRole.setCreateDate(new Date());
				try {
					return managerRoleDao.insert(managerRole) > 0;
				} catch (SQLException e) {
					e.printStackTrace();
				}
			}
		}
		return false;
	}
}
